<script setup lang="ts">
import { ref, reactive } from 'vue'
import { NAvatar, NModal, NCard } from 'naive-ui'
import 'vue-cropper/dist/index.css'
import { VueCropper } from 'vue-cropper'
import {
  CloudUpload as uploadIcon,
  Refresh as refreshIcon,
  Close as closeIcon
} from '@vicons/ionicons5'
import { RotateLeftRound as leftIcon, RotateRightRound as rightIcon } from '@vicons/material'
import { useUserStore } from '@/stores'
import { useUploadAvatar } from '@/api'

defineOptions({ name: 'AvatarEdit' })

// const emit = defineEmits(['submitted'])

const userStore = useUserStore()

const state = reactive({
  show: false,
  src: ''
})
const cropper = ref('cropper')
const option = reactive({
  img: '',
  size: 1,
  full: false,
  outputType: 'png',
  canMove: true,
  fixedBox: true,
  original: false,
  canMoveBox: true,
  autoCrop: true,
  autoCropWidth: 250,
  autoCropHeight: 250,
  centerBox: false,
  high: true,
  preview: ''
})

const initModal = () => {
  state.show = true
  option.img = userStore.avatar
}

const onTriggerUpload = () => {
  document.getElementById('upload-avatar').click()
}

const onUpload = (e) => {
  let file = e.target.files[0]

  let reader = new FileReader()
  reader.onload = (e) => {
    let data
    if (typeof e.target.result === 'object') {
      data = window.URL.createObjectURL(new Blob([e.target.result]))
    } else {
      data = e.target.result
    }

    option.img = data
  }

  reader.readAsArrayBuffer(file)
}

const realTime = (data) => {
  cropper.value.getCropData((img) => {
    option.preview = img
  })
}

const rotateLeft = () => {
  cropper.value.rotateLeft()
}

const rotateRight = () => {
  cropper.value.rotateRight()
}

const refreshCrop = () => {
  cropper.value.refresh()
}

const onSubmit = () => {
  cropper.value.getCropBlob((blob) => {
    let avatarName = userStore.avatar.split('/').pop()
    let file = new File([blob], avatarName, {
      type: blob.type,
      lastModified: Date.now()
    })

    const formData = new FormData()
    formData.append('file', file)

    // TODO 后端请求
    useUploadAvatar(formData, userStore.username).then(({ data }) => {
      state.show = false
      if (data != null) {
        userStore.avatar = data
        window.$message.success('修改成功')
      } else {
        window.$message.success('修改失败')
      }
    })
  })
}
</script>

<template>
  <input
    id="upload-avatar"
    style="display: none"
    type="file"
    accept="image/png, image/jpeg, image/jpg, image/webp"
    @change="onUpload"
  />
  <div class="avatar-edit">
    <n-avatar class="avatar" round :src="userStore.avatar" />
    <div class="mask" @click="initModal()"></div>
    <n-modal v-model:show="state.show">
      <n-card class="avatar-card" title="选择头像" :bordered="false">
        <template #header-extra>
          <closeIcon @click="state.show = false" class="close-modal" />
        </template>
        <div class="avatar-content">
          <div class="avatar-canvas">
            <vue-cropper
              ref="cropper"
              :img="option.img"
              :output-size="option.size"
              :output-type="option.outputType"
              :info="true"
              :full="option.full"
              :can-move="option.canMove"
              :can-move-box="option.canMoveBox"
              :fixed-box="option.fixedBox"
              :original="option.original"
              :auto-crop="option.autoCrop"
              :auto-crop-width="option.autoCropWidth"
              :auto-crop-height="option.autoCropHeight"
              :center-box="option.centerBox"
              @real-time="realTime"
            />
          </div>
          <div class="avatar-view">
            <div class="avatar-preview">
              <img :src="option.preview" v-show="option.preview" />
            </div>
          </div>
        </div>
        <template #footer>
          <div class="action-container">
            <div class="container-aside">
              <n-button @click="onTriggerUpload" type="primary" ghost>
                上传图片
                <template #icon>
                  <uploadIcon />
                </template>
              </n-button>

              <n-button @click="refreshCrop">
                重置
                <template #icon>
                  <refreshIcon />
                </template>
              </n-button>

              <n-button @click="rotateLeft">
                <template #icon>
                  <leftIcon />
                </template>
                左转
              </n-button>

              <n-button @click="rotateRight">
                <template #icon>
                  <rightIcon />
                </template>
                右转
              </n-button>
            </div>
            <div class="container-main">
              <n-button type="primary" @click="onSubmit">保存头像</n-button>
            </div>
          </div>
        </template>
      </n-card>
    </n-modal>
  </div>
</template>

<style scoped>
.avatar-edit {
  display: flex;
}
.avatar {
  width: 150px;
  height: 150px;
}

.mask {
  width: 150px;
  height: 150px;
  text-align: center;
  font-size: 36px;
  color: white;
  line-height: 150px;
  position: fixed;
  border-radius: 50%;
  background-color: rgba(0, 0, 0, 0);
}

.mask:hover {
  cursor: pointer;
  background-color: rgba(0, 0, 0, 0.3);
}

.mask:hover::after {
  content: '+';
}

.avatar-card {
  width: 800px;
}

.close-modal {
  height: 30px;
}

.close-modal:hover {
  cursor: pointer;
  background-color: rgba(0, 0, 0, 0.2);
  border-radius: 50%;
}

.avatar-content {
  width: 100%;
  height: 400px;
  display: flex;
}

.avatar-canvas {
  width: 400px;
  height: 400px;
  padding: 5px;
}

.avatar-view {
  flex: auto;
  display: flex;
  align-items: center;
  justify-content: center;
}

.avatar-preview {
  width: 180px;
  height: 180px;
  border-radius: 20px;
  overflow: hidden;
  border: 1px solid var(--border-color);
}

.avatar-preview img {
  width: 100%;
  height: 100%;
}

.action-container {
  display: flex;
  justify-content: space-between;
}

.container-aside {
  width: 400px;
  justify-content: space-between;
  align-items: center;
  display: flex;
  padding: 0 5px;
}
.container-main {
  flex: auto;
  display: flex;
  justify-content: center;
}
</style>
